/*
 * @Author: greyqiu greyqiu@163.com
 * @Date: 2023-06-27 16:56:34
 * @LastEditors: GreyQiu qiushaogui@aikosolar.com
 * @LastEditTime: 2023-07-18 16:28:20
 * @FileName: easy_timer.c
 * @Description: 
 * 本文件实现一个用于任务调度的定时器，通过合理调用本模块函数，可以将任务注册到定时器，
 * 定时器触发时将运行注册的任务函数，各定时器作为链表节点，在main函数while循环中遍历。
 * 
 * Copyright (c) 2023 by GreyQiu, All Rights Reserved. 
 */

#include "easy_timer.h"

easy_timer_id_t p_timerlist_head; // 链表头
easy_timer_id_t p_timerlist_end;  // 链表尾
static easy_timer_t easy_timer_list_head;

static uint16_t timer_num = 0;

/**
 * @description: 初始化easy timer
 * @return NULL
 */
void easy_timer_init(void)
{
    timer_num = 0;    
    p_timerlist_head = &easy_timer_list_head;
    p_timerlist_end  = &easy_timer_list_head;
    
    p_timerlist_head->next = p_timerlist_head;
    p_timerlist_head->last = p_timerlist_head;

    systick_init();
}

/**
 * @description: 创建一个easy timer 并插入到timer链表末尾
 * @param p_timer_id 定时器id
 * @return NULL
 */
void easy_timer_create(easy_timer_id_t p_timer_id)
{
    if (p_timer_id == NULL || p_timer_id->bDelete == false)
    {
        return;
    }
    
    p_timer_id->bDelete = false;
    
    p_timerlist_head->last->next = p_timer_id;
    p_timer_id->last = p_timerlist_head->last;
    
    p_timerlist_head->last = p_timer_id;
    p_timer_id->next = p_timerlist_head;
    
    timer_num++;
}

/**
 * @description: 删除一个easy timer 并从timer链表删除
 * @param p_timer_id 定时器id
 * @return NULL
 */
void easy_timer_delete(easy_timer_id_t  p_timer_id)
{
    if (p_timer_id->bDelete == false)
    {
        p_timer_id->last->next =  p_timer_id->next;
        p_timer_id->next->last =  p_timer_id->last;

        p_timer_id->bDelete = true;
        p_timer_id->pending = true;
    }
}

/**
 * @description: 开始运行timer
 * @param p_timer_id 定时器id
 * @param period 触发周期 单位ms
 * @param mode 触发模式 单次触发或者重复触发
 * @param timeout_handler 触发后的回调函数
 * @param p_context 回调函数传入参数指针
 * @return NULL
 */
void easy_timer_start(easy_timer_id_t p_timer_id, 
                     uint32_t period,
                     easy_timer_mode_t mode,
                     easy_timer_timeout_handler_t timeout_handler
                    )
{
    if (p_timer_id->bDelete == false) //in the list
    {
        p_timer_id->period = (uint64_t)period * TICKS_1MS; // 毫秒转换成ticks
        p_timer_id->counter = 0;
        p_timer_id->pending = false;
        p_timer_id->tickLast = GET_TIME_STAMP();
        p_timer_id->mode = mode;
        p_timer_id->cb = timeout_handler;
    }
}

/**
 * @description: 停止timer
 * @param timer_id 定时器id
 * @return NULL
 */
void easy_timer_stop(easy_timer_id_t timer_id)
{
    timer_id->pending = true;
}

/**
 * @description: 重新运行timer
 * @param timer_id 定时器id
 * @return NULL
 */
void easy_timer_restart(easy_timer_id_t timer_id)
{
    timer_id->counter = 0;
    timer_id->pending = false;
    timer_id->tickLast = GET_TIME_STAMP();
}

/**
 * @description: easy timer主任务，必须在while中调用
 * @return NULL
 */
void easy_timer_execute(void)
{
    easy_timer_t *pt;
    uint32_t TS;
    for (pt = p_timerlist_head->next; pt != p_timerlist_head; pt = pt->next) // 遍历链表每个timer节点
    {
        if (pt->pending == true) // 判断timer是否被挂起
        {
            continue;
        }

        TS = GET_TIME_STAMP(); // 获取当前计数器值

        // 根据计数器方向不同，累加easy timer的counter
        if (TIMER_DERECTION == COUNTER_DIR_UP) {
            pt->counter += ((TS - (pt->tickLast)) & MAX_TICKS);
        }
        else {
            pt->counter += (((pt->tickLast) - TS) & MAX_TICKS);
        }
        pt->tickLast = TS;

        if (pt->counter < pt->period) // 判断累计时间是否大于所设定周期
        {
            continue;
        }

        pt->counter = 0;

        if (pt->cb != NULL) {
            pt->cb(); // 执行easy timer创建时注册的回调函数
        }
        if (pt->mode == EASY_TIMER_MODE_SINGLE_SHOT)
        {
            pt->pending = true; // 单次触发模式下，触发一次后立即挂起
        }
    }
}


